package com.winning.platwebservice.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.winning.platwebservice.entity.SjyyxxEntity;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 通用校验工具类
 */
@Component
public class ValidateByJsonUtils {

    @Autowired
    EhcacheUtil ehcacheUtil;


    /**
     * 通用校验方法
     * return map 包括校验结果和错误提示信息
     */
    public Map<String, String> checkData(Map jbData, String bm) {
//        转换key大小写
        jbData = convertCase(jbData);
        List<SjyyxxEntity> listSjyxxAll = ehcacheUtil.zyCache.get("sjyxx"); //获取数据元信息

        List<SjyyxxEntity> listSjyxx = listSjyxxAll.stream().filter(SjyyxxEntity ->
                SjyyxxEntity.getSjjdm().equalsIgnoreCase(bm.toUpperCase())).collect(Collectors.toList()); //根据数据集代码过滤


        Map<String, String> map = new HashMap<>();
        String msg = ""; //返回错误信息
        String res = "1"; //校验结果 0 不通过  1 通过

        //遍历数据元配置表，校验每个入参是否符合数据元要求
        for (SjyyxxEntity sjy : listSjyxx) {

            String sjydm = sjy.getSjydm().toUpperCase();  //数据元代码
            String sjylx = sjy.getSjylx(); //数据元类型
            Integer sjyys = sjy.getSjyys(); //数据元约束
            Integer sjycdzs = sjy.getSjycdzs(); //数据元长度
            Integer sjycdxs = sjy.getSjycdxs(); //数据元长度
            String sjymrz = sjy.getSjymrz();//数据默认值
            String data = null; //接口入参


            try {
                data = jbData.get(sjydm.toUpperCase()).toString();

            } catch (Exception e) {
                //e.printStackTrace();
                data = null;
            }

            //校验非空
            if (sjyys == 0 && StringUtils.isBlank(data) && !StringUtils.isNotBlank(sjymrz)) {

                res = "0";
                msg = msg + "节点" + sjydm + "不能为空;";
            }

            if (!StringUtils.isEmpty(data)) {
                //校验数字型
                if ("int".equalsIgnoreCase(sjylx) || "numeric".equalsIgnoreCase(sjylx)) {
                    if (!data.matches("-?[0-9]+(\\.[0-9]+)?")) {
                        res = "0";
                        msg = msg + "节点" + sjydm + ",值[" + data + "]数据格式错误;";
                    } else {
                        String[] split = data.split("\\.");
                        //判断整数最大长度
                        if (sjycdzs < split[0].length()) {
                            res = "0";
                            msg = msg + "节点" + sjydm + ",值[" + data + "]整数超出最大长度" + sjycdzs + ";";
                        }
//                        判断小数 最大长度
                        if (split.length == 2) {
                            if (sjycdxs < split[1].length()) {
                                res = "0";
                                msg = msg + "节点" + sjydm + ",值[" + data + "]小数超出最大长度" + sjycdxs + ";";
                            }
                        }
                    }
                }

                if ("DATETIME".equalsIgnoreCase(sjylx) || "DATE".equalsIgnoreCase(sjylx)) {  //校验日期型
                    if (!isDate(data)) {
                        res = "0";
                        msg = msg + "节点" + sjydm + ",值[" + data + "]数据格式错误;";
                    }
                }

                if (sjylx.toUpperCase().contains("CHAR")) {  //校验字符型
                    //判断最大长度
                    if (sjycdzs < data.length()) {
                        res = "0";
                        msg = msg + "节点" + sjydm + ",值[" + data + "]超出最大长度" + sjycdzs + ";";
                    }
                }
            }
        }

        map.put("msg", msg);
        map.put("res", res);
        return map;
    }

    /**
     * 校验主键是否重复
     *
     * @param jayData
     * @param bm
     * @return
     */
    public Map<String, String> checkPrimayKey(JSONArray jayData, String bm) {
        List<SjyyxxEntity> listSjyxxAll = ehcacheUtil.zyCache.get("sjyxx"); //获取数据元信息
        List<SjyyxxEntity> listSjyxx = listSjyxxAll.stream().filter(SjyyxxEntity ->
                SjyyxxEntity.getSjjdm().equals(bm.toUpperCase())).collect(Collectors.toList()); //根据数据集代码过滤

        Map<String, String> map = new HashMap<>();
        String msg = ""; //返回错误信息
        String res = "1"; //校验结果 0 不通过  1 通过

        JSONObject objBody;
        List zjzList = new ArrayList(); //主键字段值集合
        for (int i = 0; i < jayData.size(); i++) {
            try {
                objBody = jayData.getJSONObject(i);
            } catch (JSONException e) {
                e.printStackTrace();
                objBody = null;
            }
            String zjz = ""; //联合拼接的主键值字段
            for (SjyyxxEntity sjy : listSjyxx) {
                String sjydm = sjy.getSjydm();  //数据元代码
                String sfzj = sjy.getSfzj(); //是否主键

                if ("1".equals(sfzj)) {
                    String data = null; //接口入参
                    try {
                        data = objBody.getString(sjydm.toLowerCase());
                    } catch (JSONException e) {
                        //e.printStackTrace();
                        data = null;
                    }
                    zjz = zjz + data;
                }
            }
            if (zjzList.contains(zjz)) {
                msg = "入参存在主键重复数据";
                res = "0";
                break;
            } else {
                zjzList.add(zjz);
            }
        }

        map.put("msg", msg);
        map.put("res", res);

        return map;
    }

    /**
     * 获取主键列
     *
     * @param bm
     * @return
     */
    public List<String> getPkName(String bm) {
        List<SjyyxxEntity> listSjyxxAll = ehcacheUtil.zyCache.get("sjyxx"); //获取数据元信息
        List<SjyyxxEntity> listSjyxx = listSjyxxAll.stream().filter(SjyyxxEntity ->
                SjyyxxEntity.getSjjdm().equals(bm.toUpperCase())).collect(Collectors.toList()); //根据数据集代码过滤

        List<String> pkName = new ArrayList<>();
        for (SjyyxxEntity sjy : listSjyxx) {
            String sjydm = sjy.getSjydm();  //数据元代码
            String sfzj = sjy.getSfzj(); //是否主键
            if ("1".equals(sfzj)) {
                pkName.add(sjydm);
            }
        }

        return pkName;
    }

    /**
     * 校验日期格式
     *
     * @param str
     * @return
     */
    private boolean isValidDate(String str) {
        boolean result = true;
        //判断字符串长度是否为8位
        if (str.length() == 10) {  //校验日期格式
            // 指定日期格式为四位年/两位月份/两位日期，注意yyyy/MM/dd区分大小写;
            //SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            try {
                // 设置lenient为false.
                // 否则SimpleDateFormat会比较宽松地验证日期，比如2007/02/29会被接受，并转换成2007/03/01
                format.setLenient(false);
                format.parse(str);
            } catch (ParseException e) {
                result = false;
            }
        } else {  //校验日期格式 yyyy-MM-dd HH:mm:ss
            // 指定日期格式为四位年/两位月份/两位日期，注意yyyy/MM/dd区分大小写;
            //SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            try {
                // 设置lenient为false.
                // 否则SimpleDateFormat会比较宽松地验证日期，比如2007/02/29会被接受，并转换成2007/03/01
                format.setLenient(false);
                format.parse(str);
            } catch (ParseException e) {
                result = false;
            }
        }

        return result;
    }


    public static boolean isDate(String strDate) {
        //"^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$"

        String regex = "^[0-9]{4}-(((0[13578]|(10|12))-(0[1-9]|[1-2][0-9]|3[0-1]))|(02-(0[1-9]|[1-2][0-9]))|((0[469]|11)-(0[1-9]|[1-2][0-9]|30)))($|\\s([0-1]\\d|[2][0-3])\\:[0-5]\\d\\:[0-5]\\d)$";
        Pattern pattern = Pattern
                .compile(regex);
        Matcher m = pattern.matcher(strDate);
        if (m.matches()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 将JSON中字符串转成Date类型
     *
     * @param parm
     * @return
     * @throws JSONException
     */
    public static com.alibaba.fastjson.JSONObject jsonDateConversion(com.alibaba.fastjson.JSONObject parm) throws JSONException {

        Set<String> keys = parm.keySet();
        for (String key : keys) {
            String value = parm.getString(key);
            if (DateUtil.isValidDate(value)) {
                parm.put(key, DateUtil.stringFormatDate(value));
            }
        }
        return parm;
    }

    /**
     * 将Map中字符串转成Date类型
     *
     * @return
     */
    public static Map mapDateConversion(Map parm) {

        Set<String> keys = parm.keySet();
        for (String key : keys) {
            String value = (String) parm.get(key);
            if (DateUtil.isValidDate(value)) {
                parm.put(key, DateUtil.stringFormatDate(value));
            }
        }
        return parm;
    }

    private Map convertCase(Map data) {
        Map map = new HashMap();
        Set keys = data.keySet();
        for (Object k : keys) {
            map.put(((String) k).toUpperCase(), data.get(k));
        }

        return map;
    }


}
